#include "Game.h"

void Game::init(std::string title, int x, int y)
{
    win.Create(sf::VideoMode(800, 600, 32), title);
    running = true;
    v.SetCenter(1000, 1000);
    v.SetHalfSize(400, 300);
    v.Move(-900, -900);
}


//Use this or factorys
void Game::addtile(Def def)
{
    Tile t;
    t.init(def);
    tiles[(int)def.GetVal("x")][(int)def.GetVal("y")] = t;
}

void Game::addtile(Tile t, int x, int y)
{
    tiles[x][y] = t;
}


void Game::addent(BaseOBJ* obj)
{
    tiles[obj->GetX()][obj->GetY()].SetTop(obj);
    ents.insert(ents.end(), obj);
}


void Game::addent(Def def)
{
    BaseOBJ* obj = new BaseOBJ;
    obj->init(def);
    tiles[obj->GetX()][obj->GetY()].SetTop(obj);
    ents.insert(ents.end(), obj);
}

void Game::draw()
{
    win.Clear();
    win.SetView(v);
    //Draw tiles
    for(int i = 0; i <= 99; i++)
    {
        for(int k = 0; k <= 99; k++)
        {
            Tile& t = tiles[k][i];
            win.Draw(t.getspr());
        }
    }

    for(unsigned int k = 0; k < ents.size(); k++)
    {
        if(ents[k]->isAlive())
            win.Draw(ents[k]->getspr());
    }
    //Draw player
    win.Draw(user.getspr());
    win.SetView(win.GetDefaultView());
    //Draw the interface
    win.Display();
}

void Game::update()
{
    if(!running) {return;}
    sf::Event event;
    while(win.GetEvent(event))
    {
        if(event.Type == sf::Event::Closed)
            running = false;
        if(event.Type == sf::Event::KeyPressed) //For now use this system. Later, when we have tile independnt movement, use real time
        {
            if(event.Key.Code == sf::Key::Down)
            {
                if(tiles[user.GetX()][user.GetY() + 1].isSolid() == false && tiles[user.GetX()][user.GetY() + 1].GetTop()->isSolid() == false)
                {
                    user.SetY(user.GetY() + 1);
                    v.Move(0, 64);
                }
                user.SetDir(2);
            }
            if(event.Key.Code == sf::Key::Up)
            {
                user.SetDir(0);
                if(user.GetY() - 1 < 0)
                    continue;
                if(tiles[user.GetX()][user.GetY() - 1].isSolid() == false && tiles[user.GetX()][user.GetY() - 1].GetTop()->isSolid() == false)
                {
                    user.SetY(user.GetY() - 1);
                    v.Move(0, -64);
                }
            }
            if(event.Key.Code == sf::Key::Right)
            {
                if(tiles[user.GetX() + 1][user.GetY()].isSolid() == false && tiles[user.GetX() + 1][user.GetY()].GetTop()->isSolid() == false)
                {
                    user.SetX(user.GetX() + 1);
                    v.Move(64, 0);
                }
                user.SetDir(3);
            }
            if(event.Key.Code == sf::Key::Left)
            {
                user.SetDir(1);
                if(user.GetX() - 1 < 0)
                    continue;
                if(tiles[user.GetX() - 1][user.GetY()].isSolid() == false && tiles[user.GetX() - 1][user.GetY()].GetTop()->isSolid() == false)
                {
                    user.SetX(user.GetX() - 1);
                    v.Move(-64, 0);
                }
            }
            if(user.GetX() <= 0 && user.GetX() != 0)
                user.SetX(0);
            if(user.GetY() <= 0 && user.GetY() != 0)
                user.SetY(0);
        }
    }
    //const sf::Input& in = win.GetInput();
/* //Use event based for now, real time when we don't have tile constricted movement
    if(in.IsKeyDown(sf::Key::Up))
    {
        user.SetY(user.GetY() - 1);
        std::cout << "going up\n";
    }
    if(in.IsKeyDown(sf::Key::Down))
    {
        user.SetY(user.GetY() + 1);
    }
    if(in.IsKeyDown(sf::Key::Right))
    {
        user.SetX(user.GetX() + 1);
    }
    if(in.IsKeyDown(sf::Key::Left))
    {
        user.SetX(user.GetX() - 1);
    }
*/
    //Parse entites
    for(unsigned int i = 0; i < ents.size(); i++)
    {
        //Build tile map
        int x = ents[i]->GetX();
        int y = ents[i]->GetY();
        BaseOBJ* t[3][3];
        t[0][0] = tiles[x - 1][y - 1].GetTop();
        t[1][0] = tiles[x][y - 1].GetTop();
        t[2][0] = tiles[x + 1][y - 1].GetTop();
        t[0][1] = tiles[x - 1][y].GetTop();
        t[2][1] = tiles[x + 1][y].GetTop();
        t[0][2] = tiles[x-1][y+1].GetTop();
        t[1][2] = tiles[x][y+1].GetTop();
        t[2][2] = tiles[x+1][y+1].GetTop();
        t[1][1] = tiles[x][y].GetTop();
        //Update entity
        if(ents[i]->isAlive())
            ents[i]->update(t);

        //Set tops of tiles
        tiles[x][y].SetTop(ents[i]);
    }
}

/*
Tile* Game::BuildTileArrayFromPoint(int x, int y)
{
    Tile t[3][3];
    t[0][0] = tiles[x - 1][y - 1];
    t[1][0] = tiles[x][y - 1];
    t[2][0] = tiles[x + 1][y - 1];
    t[0][1] = tiles[x - 1][y];
    t[2][1] = tiles[x + 1][y];
    t[0][2] = tiles[x-1][y+1];
    t[1][2] = tiles[x][y+1];
    t[2][2] = tiles[x+1][y+1];
    //return t;
}*/


Game Game::m_Game;
